package com.charley.icloud.common.response.result;

import com.charley.icloud.common.response.code.HttpStatus;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Data;
import lombok.EqualsAndHashCode;

import java.io.Serializable;
import java.util.List;

/**
 * HTTP Response 封装
 * 自定义通用响应结构，每次请求都返回这个
 * 前后端分离开发模式下，该类作为响应体数据结果进行数据响应
 */
@Data
@EqualsAndHashCode(callSuper = false)
public class HttpResponseResult implements Serializable {
    /**
     * 定义jackson对象
     **/
    private static final ObjectMapper MAPPER = new ObjectMapper();

    /**
     * 当前响应的状态码 使用 String 类型
     * 状态码对应的 常量参数对应类：
     * 1. HttpStatus
     * 2.
     **/
    private String resultCode;

    /**
     * 当前响应的信息（失败时返回描述信息）
     **/
    private String resultMsg;

    /**
     * 响应中的数据 具体的结果
     **/
    private Object data;

    /* ******************************************  GETTER  SETTER FUNCTION STARTER  ************************************************* */
    public String getResultCode() {
        return resultCode;
    }

    public HttpResponseResult setResultCode(String resultCode) {
        this.resultCode = resultCode;
        return this;
    }

    public String getResultMsg() {
        return resultMsg;
    }

    public HttpResponseResult setResultMsg(String resultMsg) {
        this.resultMsg = resultMsg;
        return this;
    }

    public Object getData() {
        return data;
    }

    public HttpResponseResult setData(Object data) {
        this.data = data;
        return this;
    }
    /* ********************************************  GETTER  SETTER FUNCTION END  ************************************************** */

    /* ********************************************* CONSTRUCTOR  FUNCTION STARTER  ************************************************** */
    public HttpResponseResult(String resultCode, String resultMsg, Object data) {
        this.resultCode = resultCode;
        this.resultMsg = resultMsg;
        this.data = data;
    }

    public HttpResponseResult(String resultCode, Object data) {
        this.resultCode = resultCode;
        this.data = data;
    }

    public HttpResponseResult(String resultCode, String resultMsg) {
        this.resultCode = resultCode;
        this.resultMsg = resultMsg;
    }

    public HttpResponseResult(Object data) {
        this.resultCode = HttpStatus.SC_OK;
        this.resultMsg = HttpStatus.SC_OK_MSG;
        this.data = data;
    }

    public HttpResponseResult(String resultCode) {
        this.resultCode = resultCode;
    }

    public HttpResponseResult() {
    }
    /* ************************************************ CONSTRUCTOR  FUNCTION END  ************************************************** */


    /* ******************************************  常用类型 OK ERROR BUILD 方法 STARTER  ************************************************* */
    public static HttpResponseResult error() {
        return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, HttpStatus.SC_INTERNAL_SERVER_ERROR_MSG);
    }

    public static HttpResponseResult error(String resultMsg) {
        return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, resultMsg);
    }

    public static HttpResponseResult error(String resultCode, String resultMsg) {
        return new HttpResponseResult(resultCode, resultMsg);
    }

    public static HttpResponseResult error(Integer resultCode, String resultMsg) {
        return new HttpResponseResult(resultCode.toString(), resultMsg);
    }


    public static HttpResponseResult ok() {
        return new HttpResponseResult(HttpStatus.SC_OK, HttpStatus.SC_OK_MSG);
    }

    public static HttpResponseResult ok(String msg) {
        return new HttpResponseResult(HttpStatus.SC_OK, msg);
    }

    public static HttpResponseResult ok(Object data) {
        return new HttpResponseResult(HttpStatus.SC_OK, HttpStatus.SC_OK_MSG, data);

    }

    public static HttpResponseResult noAuth() {
        return new HttpResponseResult(HttpStatus.SC_UNAUTHORIZED, HttpStatus.SC_UNAUTHORIZED_MSG);
    }

    public static HttpResponseResult noAuth(String msg) {
        return new HttpResponseResult(HttpStatus.SC_UNAUTHORIZED, msg);
    }

    public static HttpResponseResult build(String code, String msg, Object data) {
        return new HttpResponseResult(code, msg, data);
    }

    public static HttpResponseResult build(String code, String msg) {
        return build(code, msg, "");
    }
    /* ******************************************  常用类型 OK ERROR BUILD 方法 END  ************************************************* */

    /**
     * 将json 结果集转换为 Result 对象
     *
     * @param jsonData json数据
     * @param clazz    Result中的object对象
     */
    public static HttpResponseResult formatToPojo(String jsonData, Class<?> clazz) {
        Object obj = null;
        try {
            if (clazz != null) {
                JsonNode jsonNode = MAPPER.readTree(jsonData);
                JsonNode data = jsonNode.get("data");
                if (data.isObject()) {
                    obj = MAPPER.readValue(data.traverse(), clazz);
                } else if (data.isTextual()) {
                    obj = MAPPER.readValue(data.asText(), clazz);
                }
                return build(jsonNode.get("code").textValue(), jsonNode.get("msg").asText(), obj);
            }
            return MAPPER.readValue(jsonData, HttpResponseResult.class);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 没有object对象的转化
     */
    public static HttpResponseResult format(String json) {
        try {
            return MAPPER.readValue(json, HttpResponseResult.class);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * object是集合转化
     */
    public static HttpResponseResult formatToList(String jsonData, Class<?> clazz) {
        try {
            JsonNode jsonNode = MAPPER.readTree(jsonData);
            JsonNode data = jsonNode.get("data");
            Object obj = null;
            if (data.isArray() && data.size() > 0) {
                obj = MAPPER.readValue(data.traverse(),
                        MAPPER.getTypeFactory().constructCollectionType(List.class, clazz));
            }
            return build(jsonNode.get("code").textValue(), jsonNode.get("msg").asText(), obj);
        } catch (Exception e) {
            return null;
        }
    }
}
